package top.v5it.logback.push.client;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.reflect.MethodSignature;
import top.v5it.logback.push.Message;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Optional;
import java.util.function.BiPredicate;
import java.util.function.Consumer;

/**
 * 基础方法
 *
 * @author zhanpu
 * @date 2022/9/30
 */
@Slf4j
public abstract class AbstractParser {

    /**
     * 按异常类型过虑
     */
    static final BiPredicate<ErrorOutput, Exception> TEST_ERROR = (logPush, error) ->
            (ArrayUtil.isNotEmpty(logPush.errorFor()) && Arrays.stream(logPush.errorFor()).anyMatch(clazz -> error.getClass().isAssignableFrom(clazz))) ||
                    (ArrayUtil.isNotEmpty(logPush.errorForClassName()) && Arrays.stream(logPush.errorForClassName()).anyMatch(name -> StrUtil.equals(name, error.getClass().getName())));

    /**
     * 输出处理器
     *
     * @param joinPoint
     * @param e
     */
    protected void outputProcessor(JoinPoint joinPoint, Exception e) {
        final Consumer<ErrorOutput> output = t -> log.error("{}", new Message().setId(t.id())
                .setTitle(t.title()).setDescription(e.getMessage()).setSourceName(getSourceName(joinPoint)));
        getErrorOutput(joinPoint, e).ifPresent(output);
    }

    /**
     * 获取源类名称
     *
     * @param joinPoint
     * @return
     */
    private String getSourceName(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        return method.getDeclaringClass().getName();
    }

    /**
     * 是否存在注解，如果存在就获取
     *
     * @param joinPoint 切点
     * @param e         异常
     * @return {@link ErrorOutput}
     */
    abstract Optional<ErrorOutput> getErrorOutput(JoinPoint joinPoint, Exception e);
}
